import { DynamicModule, Global, Module } from '@nestjs/common';
import { PostgresqlPersistence } from 'y-postgresql';
import { setPersistence } from './utils';
import * as Y from 'yjs';
import { IWSSharedDoc } from './interfaces';

@Global()
@Module({})
export class YjsPostgresqlModule {
  static forRoot(): DynamicModule {
    return {
      module: YjsPostgresqlModule,
      providers: [
        {
          provide: 'YJS_POSTGRESQL_ADAPTER',
          useFactory: async () => {
            const pg = await PostgresqlPersistence.build(
              {
                host: 'localhost',
                port: 5433,
                database: 'postgres',
                user: 'postgres',
                password: '123456',
              },
              { tableName: 'yjs-writings', useIndex: false, flushSize: 200 },
            );
            setPersistence({
              bindState: async (docName: string, ydoc: IWSSharedDoc) => {
                const persistedYdoc = await pg.getYDoc(docName);
                const newUpdates = Y.encodeStateAsUpdate(ydoc);
                pg.storeUpdate(docName, newUpdates);
                Y.applyUpdate(ydoc, Y.encodeStateAsUpdate(persistedYdoc));
                ydoc.on('update', async (update: Uint8Array) => {
                  pg.storeUpdate(docName, update);
                });
              },
              writeState: async (docName, ydoc) => {
                return new Promise((resolve) => {
                  resolve(true);
                });
              },
            });
            return pg;
          },
        },
      ],
      exports: ['YJS_POSTGRESQL_ADAPTER'],
    };
  }
}
